
/*

// #include "AenoEngine.h"
#include "agApi/ag_win32.hpp"
// #include "agApi/ag_api_basic.h"
// #include "AenoGraphics.h"

#include <stdio.h>
#include <iostream>


// ----- Main -----

int main(int args, const char* argvs[])
{
    Aeno::WindowConfig winConfig;
    winConfig.title = "AenoEngine v0.1.0";
    winConfig.width = 800;
    winConfig.height = 600;

    Aeno::Window w1game = Aeno::Window(winConfig);
    w1game.setFPS(240);
    w1game.setVSyncBool(true);
    w1game.CreateMainWindow();

    // w1game.setFullScreenBool(true);
    // w1game.setTitle(w1game.getTitle() + " fps:240");

    // renderer 输入window类型
    Aeno::Renderer r1(w1game.getHWND());
    r1.SetClearColor( RGB( 50,102,208 ) );
    // r1.SetClearColor( RGB( 50,102,208 ) );
    // r1.SetClearColor( RGB( 0, 198, 88 ) );
    w1game.s_pRenderer = &r1;


    while (w1game.update())
    {}

    return 0;
}



*/



#include <windows.h>
#include <d2d1.h>
#include <string>




namespace ag
{
    class Color
    {
        public:
            float r,g,b,a;

        public:
            Color();
            ~Color();

        public:
            Color(float r, float g, float b, float a = 1.0f);
            Color(unsigned int rgb, float a = 1.0f);

        public:
            void setColor(float r, float g, float b, float a = 1.0f);
            void setColor(unsigned int rgb, float a = 1.0f);
    };

    Color::Color(){}
    Color::~Color(){}
    // Color
	Color::Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) 
    {

    }
	Color::Color(unsigned int rgb, float a)
	{
		setColor(rgb, a);
	}
	void Color::setColor(float r, float g, float b, float a)
	{
		this->r = r; this->g = g; this->b = b; this->a = a;
	}
	void Color::setColor(unsigned int rgb, float na)
	{
		//取完位后再除以255将范围取到0~1
		r = (rgb >> 16) / 255.0f;					//相当于0xAABBCC 取0xAA
		g = ((rgb & ~0xFF00FF) >> 8) / 255.0f;		//相当于0xAABBCC 取0xBB
		b = (rgb & ~0xFFFF00) / 255.0f;				//相当于0xAABBCC 取0xCC
		a = na;
	}

    // RGB
	unsigned int RGB_U(unsigned char red, unsigned char  green, unsigned char  blue)
	{
		// return (red << 16) + (green << 8) + blue;
    	return (red << 16) | (green << 8) | blue;
	}

	unsigned int RGB_C(Color color)
	{
		unsigned char  red = unsigned char (color.r * 255);
		unsigned char  green = unsigned char (color.g * 255);
		unsigned char  blue = unsigned char (color.b * 255);
		// return (red << 16) + (green << 8) + blue;
		return (red << 16) | (green << 8) | blue;
	}

	unsigned int RGB_F(float red, float green, float blue)
	{
		return RGB_C({red,green,blue});
	}


	// RGBA
	unsigned int RGBA_U(unsigned char  red, unsigned char  green, unsigned char  blue, unsigned char alpha)
	{
		// return (red << 16) + (green << 8) + blue;
		// return (a << 24) | (red << 16) | (green << 8) | blue;
    	return (alpha << 24) | (red << 16) | (green << 8) | blue;
	}

	unsigned int RGBA_C(Color color)
	{
		unsigned char red = unsigned char(color.r * 255);
		unsigned char green = unsigned char(color.g * 255);
		unsigned char blue = unsigned char(color.b * 255);
		unsigned char alpha = unsigned char(color.a * 255);

		// return (red << 16) + (green << 8) + blue;
		return (alpha << 24) | (red << 16) | (green << 8) | blue;
	}

	unsigned int RGBA_F(float red, float green, float blue, float alpha)
	{
		return RGBA_C({red,green,blue, alpha});
	}


}

class Renderer
{
    public:
        Renderer(HWND hWnd);
        ~Renderer();

        bool Initialize();
        // float
        void ClearColor( float red, float green, float blue, float alpha );
        void ClearColor(ag::Color color);

        void Renderer::EResize(int w, int h);

    private:
        HWND hWnd_;
        ID2D1Factory* pD2DFactory_;
        ID2D1HwndRenderTarget* pRenderTarget_;
};






Renderer::Renderer(HWND hWnd) : hWnd_(hWnd), pD2DFactory_(nullptr), pRenderTarget_(nullptr)
{
    if (!Initialize())
    {
        MessageBox(nullptr, TEXT("Renderer initialization failed!"), TEXT("Error"), MB_ICONERROR);
        return;
    }
}

Renderer::~Renderer()
{
    if (pRenderTarget_)
    {
        pRenderTarget_->Release();
    }
    if (pD2DFactory_)
    {
        pD2DFactory_->Release();
    }
}

bool Renderer::Initialize()
{
    // Create Direct2D factory
    HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory_);
    if (FAILED(hr))
    {
        return false;
    }

    // Create render target
    RECT rc;
    GetClientRect(hWnd_, &rc);
    D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
    hr = pD2DFactory_->CreateHwndRenderTarget(D2D1::RenderTargetProperties(),
        D2D1::HwndRenderTargetProperties(hWnd_, size), &pRenderTarget_);

    if (FAILED(hr))
    {
        return false;
    }

    return true;
}


void Renderer::ClearColor(ag::Color color)
{
    pRenderTarget_->BeginDraw();
    pRenderTarget_->Clear( D2D1::ColorF( color.r, color.g, color.b, color.a ) );
    pRenderTarget_->EndDraw();
}

void Renderer::ClearColor( float red, float green, float blue, float alpha )
{
    pRenderTarget_->BeginDraw();
    pRenderTarget_->Clear( D2D1::ColorF( red, green, blue, alpha ) );


    // pRenderTarget_->Resize(size);

    pRenderTarget_->EndDraw();
}

void Renderer::EResize(int w, int h)
{
    D2D1_SIZE_U size = D2D1::SizeU(w, h);
    pRenderTarget_->Resize(size);
}




class Window
{
    public:
        static LRESULT CALLBACK staticWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
        void CreateMainWindow();
    public:
        
};

HWND hWnd;
static int m_width;
static int m_height;
static std::string title;

LRESULT CALLBACK Window::staticWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_SIZE:
        {
            RECT rc;
            GetClientRect(hWnd, &rc);
            m_width = rc.right - rc.left;
            m_height = rc.bottom - rc.top;

            printf("w: %d, h:%d\n", m_width, m_height);
        }
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}






// ----- 窗口样式 -----
//WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
#define WINDOW_Without_Title_Bar WS_POPUP | WS_VISIBLE
#define WINDOW_Title_Bar WS_OVERLAPPEDWINDOW | WS_VISIBLE
#define WINDOW_Title_Bar2 WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE


void Window::CreateMainWindow()
{
    HINSTANCE  hinst = GetModuleHandle(nullptr);
    WNDCLASS      wc = { 0 };
    wc.lpszClassName = TEXT("AenoWindowCls");
    wc.style         = CS_HREDRAW | CS_VREDRAW  ;
    wc.lpfnWndProc   = staticWindowProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hinst;
    wc.hIcon         = LoadIcon(nullptr, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(nullptr, IDC_ARROW);
    wc.lpszMenuName  = nullptr;
    wc.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);


    // Window-CLASS
    if (!RegisterClass(&wc)) {
        MessageBox(nullptr, TEXT("Window registration failed!"), TEXT("Error"), MB_ICONERROR);
        // return -1;
    }

    // Create window
    RECT rect = { 0, 0, m_width, m_height };
    AdjustWindowRect(&rect, WINDOW_Title_Bar, FALSE);

    int WinWidth = rect.right - rect.left;
    int WinHeight = rect.bottom - rect.top;

    // 获取屏幕分辨率
    int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);

    // ----- 窗口在屏幕中间 -----
    int pos_x_ = (screenWidth - WinWidth) / 2;
    int pos_y_ = (screenHeight - WinHeight) / 2;

    hWnd = CreateWindow(
        TEXT("AenoWindowCls"), 
        title.c_str(), 
        WINDOW_Title_Bar,
        pos_x_,
        pos_y_,
        WinWidth, 
        WinHeight,
        nullptr, 
        nullptr,
        hinst, 
        nullptr
        );

    if (!hWnd)
    {
        MessageBox(nullptr, TEXT("Window creation failed!"), TEXT("Error"), MB_ICONERROR);
        // return -1;
    }
}


int main() {

    title = "AenoEngine v0.1.0";
    m_width = 800;
    m_height = 600;

    Window w1;

    w1.CreateMainWindow();
    UpdateWindow(hWnd);
    // Initialize renderer
    Renderer agr(hWnd);

    if (!agr.Initialize()) {
        return -1;
    }

    // Show window
    ShowWindow(hWnd, SW_SHOWNORMAL);   // SW_SHOWDEFAULT
    
    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);

        // Render a frame
        agr.ClearColor( 75/255.f, 117/255.f, 200/255.f, 1/255.f );
        agr.EResize(m_width, m_height);
    }

    DestroyWindow(hWnd);
    return (int)msg.wParam;
}



/* | CS_DBLCLKS */